package com.inspur.edp.formserver.vmmanager.util;

import com.inspur.edp.bef.bizentity.GspBusinessEntity;
import com.inspur.edp.bef.bizentity.operation.BizMgrAction;
import com.inspur.edp.bef.bizentity.pushchangesetargs.ActionChangeDetail;
import com.inspur.edp.bef.bizentity.pushchangesetargs.ActionChangeSet;
import com.inspur.edp.bef.bizentity.pushchangesetargs.ElementChangeDetail;
import com.inspur.edp.bef.bizentity.pushchangesetargs.ElementChangeSet;
import com.inspur.edp.bef.bizentity.pushchangesetargs.ObjectChangeDetail;
import com.inspur.edp.bef.bizentity.pushchangesetargs.ObjectChangeSet;
import com.inspur.edp.bef.bizentity.pushchangesetargs.PushChangeSet;
import com.inspur.edp.bef.bizentity.pushchangesetargs.PushChangeSetArgs;
import com.inspur.edp.bef.bizentity.util.StringUtil;
import com.inspur.edp.bef.bizentity.pushchangesetargs.ChangeType;
import com.inspur.edp.cef.designtime.api.IGspCommonField;
import com.inspur.edp.formserver.viewmodel.GspViewModel;
import com.inspur.edp.formserver.viewmodel.GspViewModelElement;
import com.inspur.edp.formserver.viewmodel.GspViewObject;
import com.inspur.edp.formserver.viewmodel.action.ViewModelAction;
import com.inspur.edp.formserver.viewmodel.common.ConvertUtils;
import com.inspur.edp.formserver.viewmodel.common.mapping.GspVoElementSourceType;
import com.inspur.edp.formserver.viewmodel.common.mapping.GspVoObjectSourceType;
import com.inspur.edp.lcm.metadata.api.entity.GspMetadata;
import com.inspur.edp.lcm.metadata.api.service.MetadataService;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;
import java.util.List;
import java.util.Map;

public class PushChangeSets {

  /**
   *
   * @param metadata 元数据
   * @param changeSet 推送变更集
   */
  public PushChangeSets(GspMetadata metadata, PushChangeSet changeSet) {
    this.metadata = metadata;
    this.actionChangeSets = changeSet.getActionChangeSets();
    this.objectChangeSets = changeSet.getObjectChangeSets();
    this.elementChangeSets = changeSet.getElementChangeSets();
  }

  private GspMetadata metadata;
  private List<ActionChangeSet> actionChangeSets;
  private List<ObjectChangeSet> objectChangeSets;
  private List<ElementChangeSet> elementChangeSets;

  /**
   * 推送元数据
   */
  public void pushChangeSetToMetadata() {
    pushActionChangeSets();
    pushObjectChangeSets();
    pushElementChangeSets();
    saveMetadata();
  }

  /**
   * 推送MgrAction
   */
  private void pushActionChangeSets() {
    if(this.actionChangeSets == null | this.actionChangeSets.size() == 0) {
      return;
    }
    this.actionChangeSets.forEach(set -> {
      pushAction(set);
    });
  }

  /**
   * 保存元数据
   */
  private void saveMetadata() {
    MetadataService metadataService = SpringBeanUtils.getBean(MetadataService.class);
    metadataService.saveMetadata(metadata, CheckInfoUtil.getCombinePath(metadata.getRelativePath(), metadata.getHeader().getFileName()));
  }

  private void pushAction(ActionChangeSet set) {
    ActionChangeDetail detail = set.getChangeDetail();
    PushActionChangeSet pushAction = new PushActionChangeSet();

    ViewModelAction orgAction = pushAction.getMgrActionByID(this.metadata,detail.getActionId());
    ViewModelAction newAction = null;
    if(set.getChangeDetail().getMgrAction() != null) {
      newAction = ConvertUtils.toMappedAction(set.getChangeDetail().getMgrAction(),((GspViewModel)metadata.getContent()).getID(),"");
    }

    // 新增 动作
    if(set.getChangeType().equals(ChangeType.Add) && orgAction == null && newAction != null) {
      pushAction.AddMgrAction(metadata,newAction);
      return;
    }

    // 新增参数

    if(set.getChangeType().equals(ChangeType.Add) && orgAction != null && newAction != null) {
      if(StringUtil.checkNull(set.getChangeDetail().getParameterId())) {
        return;
      }
      pushAction.addMgrActionParam(orgAction, newAction,detail.getParameterCode());
    }
    // 修改
    if(set.getChangeType().equals(ChangeType.Modify) && orgAction != null) {
      pushAction.ModifyAction(orgAction,newAction,detail);
      return;
    }

    if(set.getChangeType().equals(ChangeType.Delete) && StringUtil.checkNull(detail.getParameterCode())) {
      pushAction.deleteMgrAction(metadata,detail.getActionCode());
      return;
    }
    if(set.getChangeType().equals(ChangeType.Delete) && !StringUtil.checkNull(detail.getParameterCode())) {
      pushAction.deleteMgrActionPara(orgAction, detail.getParameterCode());
      return;
    }
  }

  private void pushObjectChangeSets() {
    if(this.objectChangeSets == null || this.objectChangeSets.size() == 0) {
      return;
    }
    this.objectChangeSets.forEach(set -> {
      pushObject(set);
    });

  }

  private void pushObject(ObjectChangeSet set) {
    ObjectChangeDetail detail = set.getChangeDetail();
    PushObjectChangeSet pushObject =  new PushObjectChangeSet();
    GspViewObject orgObject = pushObject.getObjectByID(this.metadata,detail.getBizObjectId());
    GspViewObject newObject = null;
    if(set.getChangeDetail().getBizObject() != null){
      newObject = ConvertUtils.toObject(set.getChangeDetail().getBizObject(),
          ((GspViewModel)metadata.getContent()).getMapping().getTargetMetadataPkgName(),
          ((GspViewModel)metadata.getContent()).getMapping().getTargetMetadataId(),
          detail.getParentObjIDElementId(), GspVoObjectSourceType.BeObject);
    };
    String parentObjID = set.getChangeDetail().getParentObjIDElementId();

    // 新增节点
    if(set.getChangeType().equals(ChangeType.Add) && newObject != null && !parentObjectHasBeenAdded(parentObjID)) {

      pushObject.addObject(metadata, newObject,parentObjID);
      return;
    }
    // 修改节点
    if(set.getChangeType().equals(ChangeType.Modify) && orgObject != null) {
      pushObject.modifyObject(orgObject,set.getChangeDetail());
      return;
    }
    //删除节点
    if(set.getChangeType().equals(ChangeType.Delete)) {
      pushObject.deleteObject(metadata,detail.getBizObjectId());
    }

  }

  private boolean parentObjectHasBeenAdded(String parentObjId) {
    for(ObjectChangeSet set:this.objectChangeSets) {
      if(set.getChangeType().equals(ChangeType.Add) && set.getChangeDetail().getBizObjectId().contains(parentObjId)){
        return true;
      }
    }
    return false;
  }

  private void pushElementChangeSets(){
      if(this.elementChangeSets == null || this.elementChangeSets.size() == 0) {
        return;
      }
      this.elementChangeSets.forEach(set -> {
        pushElement(set);
      });
  }

  private void pushElement(ElementChangeSet set) {
    ElementChangeDetail detail = set.getChangeDetail();
    PushElementChangeSet pushElement =  new PushElementChangeSet();
    GspViewObject orgObject = pushElement.getObjectByID(metadata,detail.getBizObjectId());
    if(orgObject == null) {
      return;
    }
    GspViewModelElement orgElement = pushElement.getElementById(orgObject,detail.getBizElementId());
    GspViewModelElement newElement = null;
    if(set.getChangeDetail().getBizElement() != null) {
      newElement = ConvertUtils.toElement(
              set.getChangeDetail().getBizElement(),
              ((GspViewModel) metadata.getContent()).getMapping().getTargetMetadataPkgName(),
              ((GspViewModel) metadata.getContent()).getMapping().getTargetMetadataId(),
              GspVoElementSourceType.BeElement);

      //TODO:目前不支持一个字段关联多个be上的字段，因此未考虑ChildAssociation数组含有多个关联的情况，支持一对多的关联后需修改
      if (set.getType().equals(ChangeType.Modify) && orgElement != null) {
        if (newElement.getChildAssociations() != null && orgElement.getChildAssociations() != null && newElement.getChildAssociations().size() > 0 && orgElement.getChildAssociations().size() > 0) {
          for (IGspCommonField newField : newElement.getChildAssociations().get(0).getRefElementCollection()) {
            for (IGspCommonField orgField : orgElement.getChildAssociations().get(0).getRefElementCollection()) {
              if (newField.getCode() != null && newField.getCode().equals(orgField.getCode())) {
                newField.setID(orgField.getID());
              }
            }
          }
        }
      }

    }

    // 新增
    if(set.getType().equals(ChangeType.Add)&& orgElement == null && newElement != null) {
      pushElement.addElement(orgObject, newElement);
      return;
    }
    // 修改
    if(set.getType().equals(ChangeType.Modify) && orgElement != null) {
      pushElement.modifyElement(orgElement, newElement, detail);
    }
    // 删除
    if(set.getType().equals(ChangeType.Delete)) {
      pushElement.deleteElement(orgObject,detail.getBizElementId());
    }

  }

}
